﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Chat
{
    /// <summary>
    /// An abstraction for connection used for commutication between one chat client
    /// with the chat server. 
    /// </summary>
    /// <typeparam name="OutCmd">
    /// Base class for outcomming chat commands, sent through this connection
    /// </typeparam>
    public abstract class Connection<OutCmd> where OutCmd : Command
    {
        public Connection() : base()
        {
        }

        /// <summary>
        /// Gets or sets the amount of time in milliseconds to wait
        /// to receive data once a read operation is initiated.
        /// </summary>
        /// <returns>
        /// The time-out value of the connection in milliseconds.
        /// The default value is 0, meaning infinite.
        /// </returns>
        public abstract int ReceiveTimeout { get; set; }

        /// <summary>
        /// Disposes the Connection instance.
        /// </summary>
        public abstract void Close();

        /// <summary>
        /// Sends the specified command through the connection,
        /// using the specified serializer.
        /// </summary>
        /// <param name="outCmd">The command to send.</param>
        /// <param name="serializer">The serializer to use when sending.</param>
        public abstract void SendCmd(
            OutCmd outCmd, CmdSerializer<OutCmd> serializer);

        /// <summary>
        /// Receives command from the connection using the specified serializer.
        /// </summary>
        /// <param name="serializer">The serializer to use for receive.</param>
        /// <returns>The received command.</returns>
        public abstract object ReceiveCmd(
            CmdSerializer<OutCmd> serializer);

        /// <summary>
        /// Gets the command receiver, which incapsultes the details of 
        /// connection implementation. Namely the serializer which is used
        /// to receive commands.
        /// </summary>
        /// <param name="serializer">
        /// The serializer the receiver will use for receiving chat commands.
        /// </param>
        /// <returns>The command receiver.</returns>
        public ICmdReceiver GetCommandReceiver(CmdSerializer<OutCmd> serializer)
        {
            return new CmdReceiver(this, serializer);
        }

        /// <summary>
        /// The implementation for ICmdReceiver
        /// </summary>
        class CmdReceiver : ICmdReceiver
        {
            protected Connection<OutCmd> Conn;
            protected CmdSerializer<OutCmd> Ser;

            public CmdReceiver(
                Connection<OutCmd> conn, CmdSerializer<OutCmd> ser)
            {
                Conn = conn;
                Ser = ser;
            }

            #region ICmdReceiver<InCmd> Members

            public object ReceiveCommand()
            {
                return Conn.ReceiveCmd(Ser);
            }

            #endregion
        }
    }
}
